/*
 * Typedef.h
 *
 *  Created on: 2011-7-5
 *      Author: yong
 */

#ifndef TYPEDEF_H_
#define TYPEDEF_H_
#include<boost/thread/condition.hpp>
#include<boost/thread/thread.hpp>
#include <boost/foreach.hpp>
#include <boost/numeric/ublas/vector.hpp>
#include <boost/numeric/ublas/vector_proxy.hpp>
#include <boost/numeric/ublas/matrix.hpp>
#include <boost/numeric/ublas/triangular.hpp>
#include <boost/numeric/ublas/lu.hpp>
#include <boost/numeric/ublas/io.hpp>
#include <boost/serialization/vector.hpp>
#include <boost/assert.hpp>
#include <vector>
#include <algorithm>
#include <stdexcept>
#include <boost/mpi/timer.hpp>
#include <boost/filesystem/operations.hpp>
#include <boost/filesystem/path.hpp>
#include <boost/filesystem/fstream.hpp>
#include <boost/tokenizer.hpp>
#include <boost/lexical_cast.hpp>
#include <numeric>
#include <functional>
#include <map>

#if DISTRIM_DOUBLE
#define SQRT std::sqrt
#define POW std::pow
#define EXP std::exp
#define LOG std::log
#define VALUE_TYPE double
#else
#define SQRT sqrtl
#define POW powl
#define EXP expl
#define LOG logl
#define VALUE_TYPE long double
#endif

// MSVC does not support varadic macro.
# if defined(_MSC_VER)
namespace CacheMode
{
	enum CacheModeEnum
	{
		FullCache, BoundedCache
	};
}

namespace OrderState
{
	enum OrderStateEnum
	{
		None, Sorted, Combined
	};
}

namespace StorageState
{
	enum StorageStateEnum
	{
		Empty, Allocated, Filled
	};
}
# else
#define DEFINE_ENUM_MACRO(ENUMNAME,ENUMS...)\
namespace \
ENUMNAME\
{\
	enum ENUMNAME##Enum\
	{\
		ENUMS\
	};\
}\

DEFINE_ENUM_MACRO(CacheMode, FullCache, BoundedCache)
DEFINE_ENUM_MACRO(OrderState, None, Sorted, Combined)
DEFINE_ENUM_MACRO(StorageState, Empty, Allocated, Filled)
#endif

#define foreach BOOST_FOREACH

namespace distrim
{

template<typename T>
inline void PrintMatrixVector(const std::vector<
		boost::numeric::ublas::matrix<T> > &mv)
{
	std::copy(mv.begin(), mv.end(), std::ostream_iterator<
			boost::numeric::ublas::matrix<T> >(std::cout, "\n"));
}

template<typename K, typename V>
class Page;

template<typename K, typename V, typename P, bool FK = true, bool FV = true>
class MemPageBoundedBuffer;

template<typename K, typename V, typename P, bool FK = true, bool FV = true>
class KeyValuePage;

template<typename K, typename V>
class KeyValue;

template<typename K, typename V, typename P>
class Mapper;

typedef boost::mutex::scoped_lock Lock;
typedef boost::mutex Mutex;
typedef boost::condition Condition;

enum MessageTag
{
	msg_any_tag,
	msg_partial_sum_tag,
	msg_param_tag,
	msg_config_tag,
	msg_cmd_tag
};

enum CmdErrorNo
{
	option_good = 31,
	option_need_help,
	option_logic_error,
	option_bad_cast_error
};

namespace mpi = boost::mpi;
namespace fs = boost::filesystem;

}

namespace std
{
template<typename T>
std::vector<boost::numeric::ublas::matrix<T> > &operator+(const std::vector<
		boost::numeric::ublas::matrix<T> > &lhs, const std::vector<
		boost::numeric::ublas::matrix<T> > &rhs)
{
	if (lhs.size() != rhs.size())
	{
		BOOST_THROW_EXCEPTION(std::invalid_argument(
				"incompatible elements in vector"));
	}
	std::vector<boost::numeric::ublas::matrix<T> > &left =
			const_cast<std::vector<boost::numeric::ublas::matrix<T> > &> (lhs);
	std::transform(left.begin(), left.end(), rhs.begin(), left.begin(),
			std::plus<boost::numeric::ublas::matrix<T> >());
	return left;
}
}

#endif /* TYPEDEF_H_ */
